<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>文件下载器</title>
    <link rel="stylesheet" th:href="@{/index.css}" />
    <link rel="stylesheet" th:href="@{/diy.css}" />
    <link rel="shortcut icon" th:href="@{/favicon.ico}">
    <!-- 引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script th:src="@{/vue.js}"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>

<body>
      <div id="app" class="content">
          <div class="head">小云下载器</div>
          <h1 id="msg"></h1>
          <input type="text" id="downUrl" class="input" name="downUrl" placeholder="请输入文件下载地址(仅支持http、https协议)" />
          <button ref="btn" v-bind:class="{'disable-button':downloadFlag}" class="button" style="vertical-align:middle" @click="download()"><span>下载文件</span></button>
          <el-button size="mini" icon="el-icon-finished" plain type="primary" @click="openFileList">历史下载文件列表</el-button>
          <div class="loader"  style="display: none">
              <span style="float: left;width: 80px;text-align: left" v-bind:class="{
                      start:this.schedule>=0 && this.schedule<=30,
                      half:this.schedule>30 && this.schedule<=70,
                      end:this.schedule >70 && this.schedule <=100
                      }">{{down}}</span>
              <div class="downClass">
                  <span v-if="this.downFile.fileSize">
                      <span v-bind:class="{
                      start:this.schedule>=0 && this.schedule<=30,
                      half:this.schedule>30 && this.schedule<=70,
                      end:this.schedule >70 && this.schedule <=100
                      }">{{this.downFile.downloaded}}</span>
                      /
                      <span class="ok">{{this.downFile.fileSize}}</span>
                  </span>
              </div>
              <el-progress :show-text="true" :percentage="schedule" :color="customColorMethod"></el-progress>
          </div>
          <el-card v-if="visible" style="width: 600px;margin: 40px auto">
              <el-descriptions title="文件信息" :column="1">
                  <el-descriptions-item label="文件名">{{this.fileInfo.fileName}}</el-descriptions-item>
                  <el-descriptions-item label="下载地址">
                      <div class="url">
                          <span>{{this.fileInfo.fileUrl}} &nbsp;</span>
                          <i class="el-icon-copy-document icon" @click="copyToClickBoard"></i>
                      </div>
                  </el-descriptions-item>
                  <el-descriptions-item label="下载用时">
                      <el-tag type="success">{{this.fileInfo.downTime}}</el-tag>
                  </el-descriptions-item>
                  <el-descriptions-item label="文件大小">
                      <el-tag>{{this.fileInfo.fileSize}}</el-tag>
                  </el-descriptions-item>
              </el-descriptions>
              <el-button v-if="fileInfo" type="success" @click="downloadEvt()">下载至本地</el-button>
          </el-card>
          <el-drawer
                  title="历史文件列表"
                  :visible.sync="drawer"
                  direction="rtl"
                  size="40%"
          >
              <span style="color: #e6a23c">（每周一凌晨2点清除文件，请及时下载文件）</span>
              <el-table
                      :data="files"
                      style="width: 100%">
                  <el-table-column prop="fileName" label="文件名称"></el-table-column>
                  <el-table-column prop="fileSize" width="100" label="文件大小"></el-table-column>
                  <el-table-column prop="createTime" label="创建时间"></el-table-column>
                  <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
                      <template slot-scope="scope">
                          <el-button
                                  size="mini"
                                  type="success"
                                  icon="el-icon-download"
                                  @click="downloadEvt(scope.row.fileUrl)"
                          >下载</el-button>
                      </template>
                  </el-table-column>
              </el-table>
          </el-drawer>
          <div class="footer">
              <span class="notice">此为练手项目，国外资源并不一定有加速效果，下载慢因为带宽不高。</span>
              <br/>
              <span class="notice">(如需加速，可以下载源码部署至国外服务器)</span>
              <br/>
              <a class="link" href="https://gitee.com/XU_JIANG_TAOXJT/file-download" target="_blank">Gitee源码公开地址</a>
          </div>
      </div>
</body>

<script>
    let task;
    let str;
    new Vue({
        el: '#app',
        data() {
            return {
                count:0,
                down:'',
                drawer:false,
                msg:null,
                downloadFlag:false,
                schedule:0,
                visible: false,
                task:null,
                fileInfo:{

                },
                downFile:{},
                files:[]
            }
        },
        methods:{
            openFileList(){
                this.queryFiles()
                this.drawer = true
            },
            queryFiles(){
              axios.get('/queryFiles')
                .then(res=>{
                    this.files = res.data;
                })
            },
            download: function () {
                if (this.downloadFlag) {
                    return;
                }
                this.schedule = 0;
                this.visible = false
                this.downloadFlag = true
                let downUrl = document.getElementById('downUrl').value;
                let flag = this.verify(downUrl);
                let msg = document.getElementById('msg');
                if (!flag) {
                    msg.innerHTML = '下载地址不合法';
                    setTimeout(() => {
                        msg.innerHTML = '';
                    }, 3000)
                    this.downloadFlag = false
                    return;
                }
                let fileName = this.getFileName(downUrl);
                let self = this;
                this.loadCloseOrOpen();
                axios.post('/download', {
                    downUrl: downUrl,
                }).then(function (response) {
                    msg.innerHTML = response.data;
                    this.msg = msg.innerHTML
                    setTimeout(() => {
                        msg.innerHTML = '';
                    }, 3000)
                    self.loadCloseOrOpen()
                    self.downloadFlag = false
                    if (this.msg === '下载成功') {
                        self.getFileInfo(fileName)
                        self.visible = true
                        let head = document.getElementsByClassName('head')[0];
                        console.log(head)
                        head.style.marginTop = '-20vh'
                    }
                })
                task = setInterval(() => {
                    this.refreshProgress(fileName)
                }, 1000);
                str = setInterval(()=>{
                    this.downStr()
                },300)
            },
            downStr(){
                if (this.count>=999){
                    this.count = 0
                }
                this.count++
                let temp = ""
                for (let i = 0; i < this.count%3+1; i++) {
                    temp+='.';
                }
                this.down = '下载中'+temp
            },
            verify(downUrl){
                if (downUrl.indexOf('http')<0 && downUrl.indexOf('https')<0){
                    return false;
                }else {
                    return true;
                }
            },
            downloadEvt(url) {
                if (!url){
                    url = this.fileInfo.fileUrl
                }
                const el = document.createElement('a');
                el.style.display = 'none';
                el.setAttribute('target', '_blank');
                /**
                 * download的属性是HTML5新增的属性
                 * href属性的地址必须是非跨域的地址，如果引用的是第三方的网站或者说是前后端分离的项目(调用后台的接口)，这时download就会不起作用。
                 * 此时，如果是下载浏览器无法解析的文件，例如.exe,.xlsx..那么浏览器会自动下载，但是如果使用浏览器可以解析的文件，比如.txt,.png,.pdf....浏览器就会采取预览模式
                 * 所以，对于.txt,.png,.pdf等的预览功能我们就可以直接不设置download属性(前提是后端响应头的Content-Type: application/octet-stream，如果为application/pdf浏览器则会判断文件为 pdf ，自动执行预览的策略)
                 */
                el.setAttribute('download', this.getFileName(url));
                el.href = url;
                document.body.appendChild(el);
                el.click();
                document.body.removeChild(el);
            },
            loadCloseOrOpen(){
                let load = document.getElementsByClassName('loader')[0];
                if (load.style.display==='none'){
                    load.style.display = ''
                }else {
                    load.style.display='none'
                }
            },
            refreshProgress(fileName){
                if (!fileName){
                    return
                }
                let self = this
                axios.get('/getDownResult/'+fileName)
                    .then(function (res){
                        if (res.data){
                            self.schedule = parseInt(res.data.downRate.substr(0,res.data.downRate.length-1))
                            self.downFile = res.data
                        }else {
                            clearInterval(task)
                            clearInterval(str)
                        }
                    })
            },
            getFileName(url){
                let fileName = url.split('/')[url.split('/').length - 1]
                if (fileName.indexOf('?')){
                    fileName = fileName.split('?')[0]
                }
                return fileName
            },
            // 获取文件信息
            getFileInfo(fileName){
                if (fileName){
                    axios.get('/getFileInfo/'+fileName).then((res)=>{
                        this.fileInfo = res.data;
                    })
                }else {
                    console.log('文件名为空')
                }

            },
            customColorMethod(percentage) {
                if (percentage < 30) {
                    return '#909399';
                } else if (percentage < 70) {
                    return '#e6a23c';
                } else {
                    return '#67c23a';
                }
            },
            //  拷贝内容到剪切板
            copyToClickBoard(){
                if (navigator.clipboard && window.isSecureContext) {
                    navigator.clipboard.writeText(this.fileInfo.fileUrl)
                        .then(() => {
                            this.$message({
                                message: '文件地址拷贝成功',
                                type: 'success'
                            });
                        })
                        .catch(err => {
                            this.$message({
                                message: '拷贝失败',
                                type: 'error'
                            });
                        })
                    return;
                } else {
                    // 创建text area
                    const textArea = document.createElement('textarea')
                    textArea.value = this.fileInfo.fileUrl
                    // 使text area不在viewport，同时设置不可见
                    document.body.appendChild(textArea)
                    textArea.focus()
                    textArea.select()
                    this.$message.success('复制成功')
                    return new Promise((res, rej) => {
                        // 执行复制命令并移除文本框
                        document.execCommand('copy') ? res() : rej()
                        textArea.remove()
                    })
                }


            }
        }
    })
</script>
</html>
